package com.visense.smart.pharm.pa.service.module.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.visense.smart.pharm.common.core.KeyValue;
import com.visense.smart.pharm.mybatis.datasource.annotation.DataSource;
import com.visense.smart.pharm.mybatis.enums.DataSourceType;
import com.visense.smart.pharm.pa.bean.base.InsertDetailMsg;
import com.visense.smart.pharm.pa.bean.base.PAFunctionId;
import com.visense.smart.pharm.pa.bean.ns.IPAInfo;
import com.visense.smart.pharm.pa.bean.ns.NSModuleBase;
import com.visense.smart.pharm.pa.common.*;
import com.visense.smart.pharm.pa.domain.TSda;
import com.visense.smart.pharm.pa.mapper.klib.DICInstructionMapper;
import com.visense.smart.pharm.pa.mapper.klib.TSdaMapper;
import com.visense.smart.pharm.pa.mapper.pa.HosInstructionUpLoadMapper;
import com.visense.smart.pharm.pa.service.DrugInfoService;
import com.visense.smart.pharm.pa.service.module.SpaceModule;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author huangchengxiao
 * @date 2024/3/14 13:06
 */
@Slf4j
@Service
public class SpaceModuleImpl extends NSModuleBase implements SpaceModule {

    @Resource
    HosInstructionUpLoadMapper hosInstructionUpLoadMapper;
    @Resource
    DICInstructionMapper dicInstructionMapper;
    @Resource
    TSdaMapper tSdaMapper;
    @Resource
    DrugInfoService drugInfoService;

    @Override
    public PAFunctionId[] GetFunIds() {
        return new PAFunctionId[]{PAFunctionId.GetInstruction, PAFunctionId.GetInstructionLink};
    }
    //************************************************
    //the format of detail xml:
    //<?xml version="1.0"?>
    //<details_xml>
    //<medicine>
    //        <dt_code>药品代码</dt_code>
    //</medicine>
    //</details_xml>

    @Override
    public int Call(IPAInfo info) {
        log.info("开始执行说明书相关内容");
        log.info("info信息打印===================start");
        log.info(JSONObject.toJSONString(info));
        log.info("info信息打印===================end");

        if (Objects.isNull(info.getDetailMsg())) {
            if (info.getDetailData().contains("<?xml")) {
				/*InsertDetailMsg detailMsg = new InsertDetailMsg();

				XmlDocument doc = new XmlDocument();
				doc.LoadXml(PAUtil.StripNonValidXMLCharacters(info.getDetailData()));
				info.getLogging().Info(PAInfo.class, "DetailData: " + doc.OuterXml);

				XmlNode node = doc.SelectSingleNode("details_xml/hosp_flag");
				if (node != null)
				{
					detailMsg.setHospFlag(node.InnerText);
				}
				node = doc.SelectSingleNode("details_xml/medicine/dt_code");
				if (node != null)
				{
					detailMsg.setMedCode(node.InnerText);
				}
				node = doc.SelectSingleNode("details_xml/medicine/his_code");
				if (node != null)
				{
					detailMsg.setMedHISCode(node.InnerText);
				}

				info.setDetailMsg(detailMsg);*/
            } else {
                info.setDetailMsg(JSONObject.parseObject(info.getDetailData(), InsertDetailMsg.class));
            }
        }
        int drugCode = 0;
        String hosInstructionId = "";
        InsertDetailMsg insertDetailMsg = (InsertDetailMsg) info.getDetailMsg();
        if (StringUtils.isNotBlank(insertDetailMsg.getMedHISCode())) {
            drugCode = drugInfoService.GetCode(info.getHospCode(), insertDetailMsg.getMedHISCode(), insertDetailMsg.getHospFlag(), true);

            if (ExistsUploadImg(info.getHospCode(), insertDetailMsg.getMedHISCode())) {
                hosInstructionId = "H" + insertDetailMsg.getMedHISCode();
            }
        } else {
            if (StringUtils.isNotBlank(insertDetailMsg.getMedCode())) {
                drugCode = Integer.parseInt(insertDetailMsg.getMedCode());
            }
            hosInstructionId = "H" + insertDetailMsg.getMedHISCode();
        }
        //FIXME 1003 前端应该不会传了,这块代码去除掉了

//C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
        ///#region UIResultMsg处理
        InsertLinkUIResultMsg uiMsg;
        if (info.getUIResultMsg() == null) {
            uiMsg = new InsertLinkUIResultMsg();
            uiMsg.setId(info.getFunId().getValue());
        } else {
            uiMsg = (InsertLinkUIResultMsg) info.getUIResultMsg();
        }

        //int nDrugType = DrugInfo.GetDrugZXYBS(drugCode, 0);
        //if (nDrugType == 3) //草药不返回pdf文件名.
        //    uiMsg.FileName = string.Empty;
        //else
        //    uiMsg.FileName = PA.Common.PaDal.PADBAccess.DrugInfo.GetInsertName(drugCode);
        uiMsg.setFileName(drugInfoService.GetInsertName(drugCode));
        //if (uiMsg.FileName == null)
        //    uiMsg.FileName = string.Empty;

        uiMsg.setLink("Detail/DrugInsertPdf/" + drugCode);
        if (StringUtils.isNotBlank(hosInstructionId)) {
            uiMsg.setLink("Detail/DrugInsertPdf/" + hosInstructionId);
        }
        info.setUIResultMsg(uiMsg);
//C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
        ///#endregion

//C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
        ///#region HISResultMsg处理
        InsertLinkHISResultMsg hisMsg;
        if (info.getHISResultMsg() == null) {
            hisMsg = new InsertLinkHISResultMsg();
        } else {
            hisMsg = (InsertLinkHISResultMsg) info.getHISResultMsg();
        }

        hisMsg.setFileName(uiMsg.getFileName());
        hisMsg.setLink(uiMsg.getLink());

        info.setHISResultMsg(hisMsg);
//C# TO JAVA CONVERTER TODO TASK: There is no preprocessor in Java:
        ///#endregion

        return 0;
    }


    /**
     * 判断对应医院药品code是否有上传的说明书
     * PADB 数据库
     *
     * @param hosDrugCode
     * @return
     */
    private boolean ExistsUploadImg(int hospCode, String hosDrugCode) {
        return hosInstructionUpLoadMapper.selectCountByHospCodeAndHosDrugCode(hospCode, hosDrugCode) > 0;
    }

    @DataSource(DataSourceType.KLIB)
    private void AddDrugName(IPAInfo info, InsertUIResultMsg msg, int drugCode) {
        String instructionName = dicInstructionMapper.getInstructionName(drugCode);
        msg.setDrugName(instructionName);

    }

    @DataSource(DataSourceType.KLIB)
    private void AddAlias(IPAInfo info, InsertUIResultMsg msg, int drugCode) {
        List<String> drugNameList = dicInstructionMapper.selectDrugName(drugCode);
        msg.setAlias(drugNameList.toArray(new String[drugNameList.size()]));

    }

    private void AddSimiliar(IPAInfo info, InsertUIResultMsg msg, int drugCode) {
        List<KeyValue> keyValues = dicInstructionMapper.selectInstructionIdAndName(drugCode);
        if (CollectionUtil.isEmpty(keyValues)) {
            return;
        }
        List<InsertMedicine> medicines = keyValues.stream().map(keyValue -> {
            InsertMedicine medicine = new InsertMedicine();
            medicine.setDrugCode(Convert.toStr(keyValue.getKey()));
            medicine.setName(Convert.toStr(keyValue.getValue()));
            return medicine;
        }).collect(Collectors.toList());
        msg.setMedicines(medicines);

    }

/*
    private void AddInstruction(IPAInfo info, InsertUIResultMsg msg, int drugCode) {
        try {
            //XmlDocument doc = info.UIResultsXmlDoc;
            //XmlElement elem = doc.CreateElement("instruction");
            //doc.DocumentElement.AppendChild(elem);

            ZXYBS zxybs = ZXYBS.forValue(DrugInfo.GetDrugZXYBS(drugCode, 0));

            switch (zxybs) {
                case Xy: //西药
                    AddWesternMedicineContent(info, msg, drugCode);
                    break;
                case Zcy: //中成药
                    AddTraditionalMedicineContent(info, msg, drugCode);
                    break;
                case Cy: //草药
                    AddHerbalMedicineContent(info, msg, drugCode);
                    break;
            }

            AppendMedicineCategoryContent(info, msg, drugCode);
        } catch (RuntimeException ex) {
            info.getLogging().Error(NSModuleBase.class, ex.getMessage());
        }
    }*/

    @DataSource(DataSourceType.KLIB)
    //TODO 好像库里面没有表 t_sda
    private void AddWesternMedicineContent(IPAInfo info, InsertUIResultMsg msg, int drugCode) {
      /*  try
        {
            String sql = "select Ym as '药品名称',tymc as '通用名称',cpym as '商品名称',yymc as '英文名称'," + "\r\n" + "                                hypy as
            '汉语拼音', zycf as '成分',hxmc as '化学名称',fzs as '分子式',fzl as '分子量'," + "\r\n" + "                                xz as '性状',syz as '适应症',
            ywgg as '规格',yfyl as '用法用量',blfy as '不良反应'," + "\r\n" + "                                jjz as '禁忌',zysx as '注意事项',yfyy as
            '孕妇及哺乳期妇女用药', etyy as '儿童用药'," + "\r\n" + "                                lnryy as '老年人用药',xhzy as '相互作用',ywgl as '药物过量',yldl as
            '药理毒理'," + "\r\n" + "                                yddlx as '药代动力学', cctj as '贮藏',pzwh as '批准文号',scqy as '生产企业' " + "\r\n" + "
                                     from t_sda  where zxybs='1' and id=@InstructionID ";

//C# TO JAVA CONVERTER NOTE: The following 'using' block is replaced by its Java equivalent:
//			using (DbHelper helper = PAAccessModule.KLIBAccess.GetDB().Clone())
            DbHelper helper = PAAccessModule.KLIBAccess.GetDB().clone();
            try
            {
                java.util.List<DbParameter> parameters = new java.util.ArrayList<DbParameter>();
                DbParameter parameter = helper.getProviderFactory().CreateParameter();
                parameter.ParameterName = "@InstructionID";
                parameter.DbType = DbType.Int32;
                parameter.setValue(drugCode);
                parameters.add(parameter);

                helper.Open();
                DataTable dt = helper.ExecuteQueryWithParameters(sql, parameters);
                if (dt.Rows.size() > 0)
                {
                    ConcatenateFields(dt.Rows[0], msg);
                }
            }
            finally
            {
                helper.dispose();
            }
        }
        catch(RuntimeException ex)
        {
            info.getLogging().Error(NSModuleBase.class, ex.Source + ex.getMessage());
        }*/
        List<TSda> tSdas = tSdaMapper.selectInfoByInstructionID("1", drugCode);
        ConcatenateFields(tSdas.get(0), msg);
    }

    @DataSource(DataSourceType.KLIB)
    private void AddTraditionalMedicineContent(IPAInfo info, InsertUIResultMsg msg, int drugCode) {
        List<TSda> tSdas = tSdaMapper.selectInfoByInstructionID("2", drugCode);
        ConcatenateFields(tSdas.get(0), msg);
       /* try
        {
            String sql = "select Ym as '药品名称',tymc as '通用名称',cpym as '商品名称',yymc as '英文名称'," + "\r\n" + "                                hypy as
            '汉语拼音', zycf as '成分',xz as '性状',syz as '功能主治/适应症', " + "\r\n" + "                                ywgg as '规格',yfyl as '用法用量',blfy as
            '不良反应',jjz as '禁忌',zysx as '注意事项'," + "\r\n" + "                                yfyy as '孕妇及哺乳期妇女用药', etyy as '儿童用药',lnryy as '老年人用药',"
             + "\r\n" + "                                xhzy as '相互作用',ywgl as '药物过量',yldl as '药理毒理',yddlx as '药代动力学', " + "\r\n" + "
                                cctj as '贮藏',pzwh as '批准文号',scqy as '生产企业' " + "\r\n" + "                                from t_sda where zxybs='2'
                                 and id=@InstructionID ";

//C# TO JAVA CONVERTER NOTE: The following 'using' block is replaced by its Java equivalent:
//			using (DbHelper helper = PAAccessModule.KLIBAccess.GetDB().Clone())
            DbHelper helper = PAAccessModule.KLIBAccess.GetDB().clone();
            try
            {
                java.util.List<DbParameter> parameters = new java.util.ArrayList<DbParameter>();
                DbParameter parameter = helper.getProviderFactory().CreateParameter();
                parameter.ParameterName = "@InstructionID";
                parameter.DbType = DbType.Int32;
                parameter.setValue(drugCode);
                parameters.add(parameter);

                helper.Open();
                DataTable dt = helper.ExecuteQueryWithParameters(sql, parameters);

                if (dt.Rows.size() > 0)
                {
                    ConcatenateFields(dt.Rows[0], msg);
                }
            }
            finally
            {
                helper.dispose();
            }
        }
        catch(RuntimeException ex)
        {
            info.getLogging().Error(NSModuleBase.class, ex.Source + ex.getMessage());
            return;
        }*/
    }

    @DataSource(DataSourceType.KLIB)
    private void AddHerbalMedicineContent(IPAInfo info, InsertUIResultMsg msg, int drugCode) {
        List<TSda> tSdas = tSdaMapper.selectInfoByInstructionID("3", drugCode);
        ConcatenateFields(tSdas.get(0), msg);
        /*try
        {
            String sql = "select Ym as '药品名称',tymc as '品名',hypy as '汉语拼音',yymc as '拉丁名'," + "\r\n" + "                                    zycf as
            '来源',xz as '性状',yldl as '鉴别',jjz as '检查',yfyy as '浸出物', " + "\r\n" + "                                    ywgg as '含量测定',yddlx as '炮制',
            blfy as '性味与归经',syz as '功能与主治'," + "\r\n" + "                                    yfyl as '用法与用量',zysx as '注意',cctj as '储藏' " + "\r\n" +
             "                                    from t_sda where zxybs='3' and id=@InstructionID";

//C# TO JAVA CONVERTER NOTE: The following 'using' block is replaced by its Java equivalent:
//			using (DbHelper helper = PAAccessModule.KLIBAccess.GetDB().Clone())
            DbHelper helper = PAAccessModule.KLIBAccess.GetDB().clone();
            try
            {
                java.util.List<DbParameter> parameters = new java.util.ArrayList<DbParameter>();
                DbParameter parameter = helper.getProviderFactory().CreateParameter();
                parameter.ParameterName = "@InstructionID";
                parameter.DbType = DbType.Int32;
                parameter.setValue(drugCode);
                parameters.add(parameter);

                helper.Open();
                DataTable dt = helper.ExecuteQueryWithParameters(sql, parameters);

                if (dt.Rows.size() > 0)
                {
                    ConcatenateFields(dt.Rows[0], msg);
                }
            }
            finally
            {
                helper.dispose();
            }
        }
        catch(RuntimeException ex)
        {
            info.getLogging().Error(NSModuleBase.class, ex.Source + ex.getMessage());
        }*/
    }

    //添加药理分类信息
    private void AppendMedicineCategoryContent(IPAInfo info, InsertUIResultMsg msg, int drugCode) {
       /* try
        {
            int length = 0;
            int index = 0;
            String codes = "";
            StringBuilder sb = new StringBuilder();

            String sql = "select a.fldm from t_fl a,t_sda b where b.ID= @InstructionID and a.ywzbm = b.mID and a.fldm like '01%' ";

//C# TO JAVA CONVERTER NOTE: The following 'using' block is replaced by its Java equivalent:
//			using (DbHelper helper = PAAccessModule.KLIBAccess.GetDB().Clone())
//            DbHelper helper = PAAccessModule.KLIBAccess.GetDB().clone();
            try
            {
                *//*java.util.List<DbParameter> parameters = new java.util.ArrayList<DbParameter>();
                DbParameter parameter = helper.getProviderFactory().CreateParameter();
                parameter.ParameterName = "@InstructionID";
                parameter.DbType = DbType.Int32;
                parameter.setValue(drugCode);
                parameters.add(parameter);

                helper.Open();
                DataTable dt = helper.ExecuteQueryWithParameters(sql, parameters);*//*

                List<String> fldmList = tSdaMapper.selectFldmByInstrunctionId(drugCode);

                if (CollectionUtil.isNotEmpty(fldmList))
                {
                    List<String> list = new java.util.ArrayList<String>();
                    for (String row : fldmList)
                    {
                        codes = row[0].toString();

                        while (codes.length() > 2)
                        {
                            if (!list.contains(codes))
                            {
                                list.add(codes);
                            }
                            codes = codes.substring(0, codes.length() - 2);
                        }
                    }

                    sql = "select fldm,flname,mwbz ,LENGTH(fldm)/2 as jb from t_flbase" + "\r\n" + "                            where fldm like
                    '01%' and fldm in ('',@Code) order by fldm";

                    parameters = new java.util.ArrayList<DbParameter>();
                    parameter = helper.getProviderFactory().CreateParameter();
                    parameter.ParameterName = "@Code";
                    parameter.DbType = DbType.String;
//C# TO JAVA CONVERTER TODO TASK: Lambda expressions and anonymous methods are not converted by C# to Java Converter:
                    parameter.setValue(new Func<java.util.List<String>, String>((x) =>)
                    {
//C# TO JAVA CONVERTER TODO TASK: There is no equivalent to implicit typing in Java:
                        var s = "";
//C# TO JAVA CONVERTER TODO TASK: There is no equivalent to implicit typing in Java:
                        for (var item : x)
                        {
                            s += "'" + item + "',";
                        }
                        return s.substring(0, s.getLength() - 1);
                    }
				   )(list);
                    parameters.add(parameter);

                    dt = helper.ExecuteQueryWithParameters(sql, parameters);

                    sb.append("<nodes value='药理分类'>");
                    int count = 0;
                    for (DataRow row : dt.Rows)
                    {
                        length = Integer.parseInt(row["jb"].toString());
                        if (length == index)
                        {
                            if (Integer.parseInt(row["mwbz"].toString()) == 0)
                            {
                                codes = "<node name='" + row["flname"].toString() + "' code='" + row["fldm"].toString() + "'></node>";
                            }
                            else
                            {
                                codes = "<node name='" + row["flname"].toString() + "' code='" + row["fldm"].toString() + "'>";
                                count++;
                            }
                            sb.append(codes);
                        }
                        else if (length > index)
                        {
                            if (Integer.parseInt(row["mwbz"].toString()) == 0)
                            {
                                codes = "<node name='" + row["flname"].toString() + "' code='" + row["fldm"].toString() + "'></node>";
                            }
                            else
                            {
                                codes = "<node name='" + row["flname"].toString() + "' code='" + row["fldm"].toString() + "'>";
                                count++;
                            }
                            sb.append(codes);
                        }
                        else if (length < index)
                        {
                            for (int i = 0; i < index - length; i++)
                            {
                                codes = codes + "</node>";
                                count--;
                            }
                            if (Integer.parseInt(row["mwbz"].toString()) == 0)
                            {
                                codes = codes + "<node name='" + row["flname"].toString() + "' code='" + row["fldm"].toString() + "'></node>";
                            }
                            else
                            {
                                codes = codes + "<node name='" + row["flname"].toString() + "' code='" + row["fldm"].toString() + "'>";
                                count++;
                            }
                            sb.append(codes);
                        }
                        index = length;
                        codes = "";
                    }
                    //结束后补齐</node>
                    for (int i = 0; i < count; i++)
                    {
                        codes = codes + "</node>";
                    }
                    codes += "</nodes>";
                    sb.append(codes);

                    msg.setClassify(sb.toString());
                }
            }
            finally
            {
                helper.dispose();
            }
        }
        catch(RuntimeException ex)
        {
            info.getLogging().Error(NSModuleBase.class, ex.Source + ex.getMessage());
        }*/
    }

    //TODO 这层字段逻辑待确定吧
    public static void ConcatenateFields(TSda row/*DataRow row*/, InsertUIResultMsg msg) {
       /* for (DataColumn column : row.Table.Columns)
        {
            if (!Convert.IsDBNull(row[column.Ordinal]))
            {
                String value = String.valueOf(row[column.Ordinal]).trim();
                if (value.length() > 0)
                {
                    if (msg.getInserts() == null)
                    {
                        msg.setInserts(new java.util.ArrayList<InsertContent>());
                    }

                    InsertContent content = new InsertContent();
                    content.setSelected(0);
                    content.setTitle(column.ColumnName);
                    content.setColor("");
                    content.setContent(value);
                    msg.getInserts().add(content);
                }
            }
        }*/
        if (Objects.nonNull(row)) {
            if (Objects.isNull(msg.getInserts())) {
                msg.setInserts(new ArrayList<>());
            }
            InsertContent content = new InsertContent();
            content.setSelected(0);
           /* content.setTitle(column.ColumnName);
            content.setColor("");
            content.setContent(value);*/
            msg.getInserts().add(content);

        }
    }
}
